package yc.gg.Interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import yc.gg.constants.RedisConstants;
import yc.gg.utils.JwtUtils;
import yc.gg.utils.Result;
import yc.gg.utils.UserHolder;
import yc.gg.vo.UserVO;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static yc.gg.constants.RedisConstants.LOGIN_USER_KEY;

/**
 * 登录拦截器
 * 若未登录则直接拦截
 * 若登录则刷新token
 * @author：Fuyue
 */
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws IOException {
        try {
            // 1. Token获取
            String token = getTokenFromRequest(request);
            if (StrUtil.isBlank(token)) {
                return unauthorizedResponse(response, "请先登录");
            }

            // 2. 验证JWT有效性
            if (!JwtUtils.validateToken(token)) {
                return unauthorizedResponse(response, "非法凭证");
            }

            // 3. Redis缓存校验
            String tokenKey = LOGIN_USER_KEY + token;
            // 获取哈希数据
            Map<Object, Object> userDataMap = stringRedisTemplate.opsForHash().entries(tokenKey);

            if (userDataMap.isEmpty()) {
                return unauthorizedResponse(response, "登录已过期");
            }

            // 4. 用户信息转换
            Map<String, String> userDataStringMap = new HashMap<>();
            for (Map.Entry<Object, Object> entry : userDataMap.entrySet()) {
                userDataStringMap.put(entry.getKey().toString(), entry.getValue().toString());
            }
            UserVO userVO = new UserVO();
            userVO.setOpenid(userDataStringMap.get("openid"));
            userVO.setToken(token);
            userVO.setSessionKey(userDataStringMap.get("sessionKey"));

            if (userVO.getOpenid() == null) {
                return unauthorizedResponse(response, "用户状态异常");
            }

            // 5. 保存上下文并续期
            UserHolder.saveUser(userVO);

            stringRedisTemplate.expire(tokenKey,
                    RedisConstants.LOGIN_USER_TTL,
                    TimeUnit.MINUTES);
            return true;
        } catch (Exception e) {
            log.error("认证流程异常: {}", e.getMessage());
            return unauthorizedResponse(response, "系统繁忙");
        }
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (StrUtil.isNotBlank(token)) {
            return token;
        }
        // 若请求头中没有，再尝试从请求参数中获取
        return request.getParameter("token");
    }

    private boolean unauthorizedResponse(HttpServletResponse response,
                                         String message) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSONUtil.toJsonStr(Result.error(message)));
        return false;
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) {
        UserHolder.removeUser();
    }
}